package installer.test;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.Adler32;
import java.util.zip.CRC32;

public class OnlineInstallerHelper{
	private static String filePrefix = "http://localhost/content/hdev/";
	
	public static List<String> getFileInstallList(){
		List<String> fileList = new ArrayList<String>();
		
		fileList.add("JumpStarter.jar");
		fileList.add("AutoUpdater.jar");
		fileList.add("Common.jar");
		fileList.add("Patcher.jar");
		fileList.add("currentVersions.properties");
		fileList.add("updateSites.properties");
		
		return fileList;
	}
	
	//private static int RETRY_LIMIT = 3;

	public static void downloadInstallFiles(List<String> installFiles){
		int fileCount = installFiles.size();
		for(int i = 0; i < fileCount; i++){
			try{
				download(installFiles.get(i));
			}catch(NoSuchAlgorithmException e){
				// TODO Auto-generated catch block
				e.printStackTrace();
			}catch(IOException e){
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	

	private static boolean download(String fileName) throws IOException, NoSuchAlgorithmException{
		// start timing
		long startMillis = System.currentTimeMillis();
		long timeAdler32 = 0L;
		long timeCRC32 = 0L;
		long timeMD5 = 0L;
		long timeSHA1 = 0L;
		long timeWrite = 0L;
		long timeCalc = 0L;
		long timeRead = 0L;
		long start = 0L;
		long startDload = 0L;
		//long currentDuration;
		long sDur = startMillis;
		long eDur;
		long dur;
		int startBytes = 0;

		URL url = new URL(filePrefix + fileName);
		System.out.println(filePrefix + fileName);

		// String fileName = "usr.zip";
		// URL url = new URL("http://localhost/content/" + fileName);

		// String fileName = "test.abc";
		// URL url = new
		// URL("http://livelink.thrivent.com/Livelink/llisapi.dll?func=ll&objId=31318351&objAction=download&viewType=1");

		URLConnection connection = url.openConnection();
		int fileSize = connection.getContentLength();
		// int fileSize = 1000000;
		System.out.println(fileSize);

		InputStream inStream = url.openStream();
		DataInputStream dis = new DataInputStream(new BufferedInputStream(inStream));
		DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(fileName)));

		

		MessageDigest checksumMD5 = MessageDigest.getInstance("MD5");
		MessageDigest checksumSHA1 = MessageDigest.getInstance("SHA-1");
		Adler32 checksumAdler32 = new Adler32();
		CRC32 checksumCRC32 = new CRC32();
		int bytesRead = 0;
		int totalBytes = 0;
		byte data[] = new byte[1024];
		start = System.currentTimeMillis();
		startDload = start;
		int prevProgress = 0;
		System.out.println("0%.....................50%....................100%");
		while((bytesRead = dis.read(data)) > -1){
			totalBytes += bytesRead;
			timeRead += (System.currentTimeMillis() - start);

			start = System.currentTimeMillis();
			dos.write(data, 0, bytesRead);
			timeWrite += (System.currentTimeMillis() - start);
			start = System.currentTimeMillis();
			checksumAdler32.update(data, 0, bytesRead);
			timeAdler32 += (System.currentTimeMillis() - start);
			start = System.currentTimeMillis();
			checksumCRC32.update(data, 0, bytesRead);
			timeCRC32 += (System.currentTimeMillis() - start);
			start = System.currentTimeMillis();
			checksumMD5.update(data, 0, bytesRead);
			timeMD5 += (System.currentTimeMillis() - start);
			start = System.currentTimeMillis();
			checksumSHA1.update(data, 0, bytesRead);
			timeSHA1 += (System.currentTimeMillis() - start);

			start = System.currentTimeMillis();
			int progress = Math.round((100f * totalBytes) / fileSize) / 2;

			//currentDuration = System.currentTimeMillis() - startMillis + 1;
			//double averageSpeed = 1 * totalBytes / currentDuration;

			eDur = System.currentTimeMillis();
			dur = eDur - sDur + 1;
			//double currentSpeed = 1 * (totalBytes - startBytes) / dur;
			if(dur >= 5000d){
				sDur += (dur / 2);
				startBytes += ((totalBytes - startBytes) / 2);
			}
			//dlp.setCurrentSpeed(currentSpeed);
			//dlp.setAverageSpeed(averageSpeed);
			//dlp.setProgress(progress);

			while(progress > prevProgress){
				System.out.print(".");
				prevProgress++;
			}

			// System.out.println(totalBytes);
			// System.out.println(progress);
			// if(bytesRead == 0)
			// System.out.println(bytesRead);

			timeCalc += (System.currentTimeMillis() - start);

			start = System.currentTimeMillis();
		}
		System.out.println();
		//properties.setProperty(module.getModuleName(), module.toString());

		start = System.currentTimeMillis();
		String resultMD5 = "";
		data = checksumMD5.digest();
		for(int i = 0; i < data.length; i++){
			resultMD5 += Integer.toString((data[i] & 0xff) + 0x100, 16).substring(1);
		}
		timeMD5 += (System.currentTimeMillis() - start);

		start = System.currentTimeMillis();
		String resultSHA1 = "";
		data = checksumSHA1.digest();
		for(int i = 0; i < data.length; i++){
			resultSHA1 += Integer.toString((data[i] & 0xff) + 0x100, 16).substring(1);
		}
		timeSHA1 += (System.currentTimeMillis() - start);

		System.out.println("Bytes:\t\t" + totalBytes);
		System.out.println("Adler32:\t" + timeAdler32 + "ms\t" + checksumAdler32.getValue());
		System.out.println("CRC32:\t\t" + timeCRC32 + "ms\t" + checksumCRC32.getValue());
		System.out.println("MD5:\t\t" + timeMD5 + "ms\t" + resultMD5);
		System.out.println("SHA1:\t\t" + timeSHA1 + "ms\t" + resultSHA1);
		System.out.println("Read:\t\t" + timeRead + "ms\t");
		System.out.println("Write:\t\t" + timeWrite + "ms\t");
		System.out.println("Calc:\t\t" + timeCalc + "ms\t");
		long waste = (System.currentTimeMillis() - startDload) - (timeAdler32 + timeCRC32 + timeMD5 + timeSHA1 + timeRead + timeWrite + timeCalc);
		System.out.println("Waste:\t\t" + waste + "ms\t");

		dos.flush();
		dos.close();
		dis.close();

		boolean checksumPass = true;
/*
		// NOTE: If unsupported checksum is specified, the checksum will PASS
		if(module.getChecksumType() != null && module.getChecksumType().length() > 0){
			System.out.println("Checksum type: >" + module.getChecksumType() + "<");
			System.out.println("Checksum value: >" + module.getChecksumValue() + "<");
			if(module.getChecksumType().equals("Adler32")){
				System.out.println("Adler32");
				if(!module.getChecksumValue().equals(Long.toString(checksumAdler32.getValue())))
					checksumPass = false;
			}else if(module.getChecksumType().equals("CRC32")){
				System.out.println("CRC32");
				if(!module.getChecksumValue().equals(Long.toString(checksumCRC32.getValue())))
					checksumPass = false;
			}else if(module.getChecksumType().equals("MD5")){
				System.out.println("MD5");
				if(!module.getChecksumValue().equals(resultMD5))
					checksumPass = false;
			}else if(module.getChecksumType().equals("SHA1")){
				System.out.println("SHA1");
				if(!module.getChecksumValue().equals(resultSHA1))
					checksumPass = false;
			}else
				System.out.println("Unsupported checksum (default=PASS)");
		}else
			System.out.println("No checksum (default=PASS)");
*/
		// End timing
		DecimalFormat df = new DecimalFormat("#.#");
		System.out.println((System.currentTimeMillis() - startMillis) + "ms - " + df.format((1d * fileSize / (System.currentTimeMillis() - startMillis))) + "KB/s");

		return checksumPass;
	}
}
